package com.ccod.mapper.mapper.core.chain;

import com.google.common.collect.Lists;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;

import java.util.List;
import java.util.Objects;

/**
 * 核心业务执行链
 *
 * @author: ccod
 * @data: 2020/11/10 21:54
 **/
public class CoreServiceChain<R> {

    private static final Log log = LogFactory.getLog(CoreServiceChain.class);

    protected List<CoreServiceProcess> serviceProcessList = Lists.newArrayList();

    /**
     * 功能描述: <br>
     * 〈核心业务执行模板，借鉴spring拦截器处理〉
     *
     * @Param: [context]
     * @Return: void
     * @Author: Ccod
     * @Date: 2020/12/5 11:35
     */
    public void execute(R context) {
        if (context == null) {
            throw new IllegalArgumentException("上下文为空");
        }
        CoreServiceProcess coreServiceProcess = null;
        for (CoreServiceProcess process : serviceProcessList) {
            if(Objects.isNull(process)){
                continue;
            }
            if (log.isDebugEnabled()) {
                log.debug("process:[" + process + "] start");
            }
            try {
                coreServiceProcess = process;
                //前置校验
                if (!coreServiceProcess.preCheck(context)) {
                    if (log.isDebugEnabled()) {
                        log.debug("process:[" + process + "] 前置校验未通过");
                    }
                    if(process.isInterrupt(context)){
                        break;
                    }else {
                        continue;
                    }
                }
                //任务执行
                coreServiceProcess.process(context);
                //任务完成回调
                coreServiceProcess.complete(context);
                if (log.isDebugEnabled()) {
                    log.debug("process:[" + process + "] end");
                }
            } catch (Throwable ex) {
                log.error("process:[" + coreServiceProcess + "] throw Throwable", ex);
                //异常回调
                coreServiceProcess.hasError(ex);
                //是否中断责任链
                if(process.isInterrupt(context)){
                    break;
                }else {
                    continue;
                }
            }
        }
    }

    public void setServiceProcessList(List<CoreServiceProcess> serviceProcessList) {
        this.serviceProcessList = serviceProcessList;
    }
}
